import { instantiate } from 'cc';
import { UITransform } from 'cc';
import { Button } from 'cc';
import { Vec3 } from 'cc';
import { Prefab } from 'cc';
import { _decorator, Component, Node } from 'cc';
import { EditorUI } from './EditorUI';
import { Sprite } from 'cc';
import { PointInfo } from '../bundle/utils/Types';
import { Size } from 'cc';
import { Layers } from 'cc';
import { Vec2 } from 'cc';
import { JsonAsset } from 'cc';
import Config from '../bundle/utils/Config';
import { ScrollView } from 'cc';
import { Toggle } from 'cc';
import { EditBox } from 'cc';
import { Label } from 'cc';
import { Color } from 'cc';
import { RandomUtil } from '../bundle/common/src/util/RandomUtil';
import { EditorOperate } from './EditorOperate';
const { ccclass, property } = _decorator;

@ccclass('EditorManager')
export class EditorManager extends Component {

    @property( {type: EditorUI, displayName: "地板" } )
    ui: EditorUI = null;

    @property( {type: Node, displayName: "地板" } )
    baseNode: Node = null;

    @property( {type: Prefab, displayName: "六边形地板" } )
    brickPre: Prefab = null;

    @property( {type: Prefab, displayName: "查看块预制体" } )
    lookPre: Prefab = null;
    
    @property( {type: Number, displayName: "宽长度" } )
    horizontalSize: number = 7;

    @property( {type: Number, displayName: "高长度" } )
    verticalSize: number = 7;
    
    @property( {type: JsonAsset, displayName: "关卡" } )
    targetJson: JsonAsset = null;

    // 地板的数组
    private grids: PointInfo[][] = []
    // 颜色池数组
    private colors: number[][] = []
    // 当前颜色
    private currentColor: number = 0
    private isOperatePool: boolean = false
    private isOperateFloor: boolean = false
    private isOperateRemove: boolean = false
    private isRandomAdd: boolean = false
    private isSelectColor: boolean = false

    // 指向当前捆
    private curBundle: number = -1
    private pointLoc: number = 10

    private operateCtrl: EditorOperate = null

    protected onLoad(): void {
        this.operateCtrl = this.getComponent(EditorOperate)
    }

    protected start(): void {
        this.initGround()
    }

    // --------------------- 初始化 --------------------- //
    private initGround() {
        this.baseNode.removeAllChildren()
        this.grids = []
        
        for (var ix = 0; ix < this.horizontalSize; ix++) {
            const rows = []
            for (var iz = 0; iz < this.verticalSize; iz++) {
                var brick = instantiate( this.brickPre )

                const transform = brick.getChildByName("六边形").getComponent(UITransform)
                const posX = ix * (transform.width + 5) - ((this.horizontalSize - 1) * (transform.width + 5) * 0.5) + ((iz % 2 != 0) ? transform.width / 2 : 0 )
                const posY = (this.verticalSize - 1 - iz) * transform.height * 0.8 - ((this.verticalSize - 1) * transform.height * 0.8 * 0.5)

                brick.position = new Vec3( posX, posY)
                brick.name = ix + "_" + iz
                brick.parent = this.baseNode
                
                const buttonComponent = brick.getChildByName("按钮").addComponent(Button)
                buttonComponent.node.on(Node.EventType.TOUCH_END, () => this.itemClicked(buttonComponent.node.parent))

                rows.push(new PointInfo())
            }

            this.grids.push(rows)
        }

        this.operateCtrl.drawFloor(this.horizontalSize, this.verticalSize)
    }
    
    // --------------------- 内部方法 --------------------- //
    private updateBrick(x: number, z: number, info: PointInfo) {
        const brickNode = this.baseNode.getChildByName(x + "_" + z)
        
        brickNode.getChildByName("六边形").getChildByName("内边").active = false
        brickNode.getChildByName("放置").removeAllChildren()

        if (info.isOpened == true) {
            brickNode.getChildByName("六边形").getChildByName("内边").active = info.isOpened
        }

        for (var i = 0; i < info.blocks.length; i++) {
            // const node = new Node()
            // node.layer = Layers.Enum.UI_2D
            // node.addComponent(Sprite)
            // node.getComponent(Sprite).spriteFrame = this.ui.frames[info.blocks[i]]
            // node.getComponent(UITransform).contentSize = new Size(40, 40)
            // node.position = new Vec3(i * -20, i * 20)
            // node.parent = brickNode.getChildByName("放置")

            const lookNode = instantiate(this.lookPre)
            lookNode.getChildByName("背景").getComponent(Sprite).spriteFrame = this.ui.frames[info.blocks[i]]
            lookNode.position = new Vec3(0, i * 7)
            lookNode.parent = brickNode.getChildByName("放置")
        }

        this.operateCtrl.updateBrick(x, z, info)
    }

    // 往容器中添加一块
    private contentAddBlock(color: number) {
        const node = new Node()
        node.layer = Layers.Enum.UI_2D
        node.addComponent(Sprite)
        node.getComponent(Sprite).spriteFrame = this.ui.frames[color]
        node.getComponent(UITransform).contentSize = new Size(40, 40)
        node.position = new Vec3(this.pointLoc, 0)

        this.pointLoc += 50
        
        this.ui.scrollView.content.addChild(node)
        this.ui.scrollView.content.getComponent(UITransform).contentSize = new Size(this.pointLoc, 100)
    }
    
    // 选择一个塔的位置，获取其六边的塔
    private getRimTower(x: number, z: number) {
        const closees = []
        var dirs = []
        if (z % 2 != 0) {
            // 凹进去的
            dirs = [new Vec2(1, 0), new Vec2(-1, 0), new Vec2(0, 1), new Vec2(0, -1), new Vec2(1, -1), new Vec2(1, 1)]
        } else {
            dirs = [new Vec2(1, 0), new Vec2(-1, 0), new Vec2(0, 1), new Vec2(0, -1), new Vec2(-1, -1), new Vec2(-1, 1)]
        }

        for (var i = 0; i < dirs.length; i++) {
            const newDir = new Vec2(x + dirs[i].x, z + dirs[i].y)

            if (this.checkInArea(newDir.x, newDir.y)) {
                closees.push(this.grids[newDir.x][newDir.y])
            }
        }

        return closees
    }

    // 判断一个位置是否超出显示
    private checkInArea(x: number, z: number) {
        if (x >= 0 && x < this.grids.length) {
            if (z >= 0 && z < this.grids[x].length) {
                return true
            }
        }

        return false
    }

    // 控制器操作
    public operateAtLoc(x: number, z: number, sender: Node) {
        const info = this.grids[x][z]
        
        // 判断是否删除操作
        if (this.isOperateRemove) {
            if (info.blocks.length > 0) {
                info.blocks.splice(info.blocks.length - 1, 1)

                console.log (sender.name)
                const lastBrick = sender.getChildByName("柱体").children[sender.getChildByName("柱体").children.length - 1]
                lastBrick.removeFromParent()
            }
        } else {
            info.x = x
            info.z = z
            
            if (this.isOperateFloor) {            
                if (info.blocks.length <= 0) {
                    info.isOpened = !info.isOpened
                }
            } else {
                if (this.isRandomAdd) {
                    const count = parseInt(this.ui.brickCountInput.string)
                    if (count > Config.colorCount) {
                        console.error("输出的数超出颜色数量，输入数值需要小于 " + Config.colorCount)
                        return
                    } else {
                        var colorArr = []
                        for (var i = 0; i < Config.colorCount; i++) {
                            if (info.blocks.length > 0) {
                                if (info.blocks[info.blocks.length - 1] == i)
                                    continue
                            }
                            colorArr.push(i)
                        }
    
                        colorArr = Config.shuffle(colorArr)
                        colorArr = colorArr.splice(0, count)
                    }

                    for (var i = 0; i < colorArr.length; i++) {
                        info.blocks.push(colorArr[i])
                    }
                } else {
                    info.blocks.push(this.currentColor)
                }
                info.isOpened = true
                this.updateBrick(x, z, info)
            }
            
            sender.getChildByName("查看").active = info.isOpened
        }
    }

    // --------------------- 事件 --------------------- //
    private itemClicked(sender: Node) {
        this.ui.currentBrick.string = sender.name
        const arr = sender.name.split("_")
        const x = parseInt( arr[0] )
        const z = parseInt( arr[1] )
        
        const info = this.grids[x][z]
        
        // 判断是否删除操作
        if (this.isOperateRemove) {
            if (info.blocks.length > 0) {
                info.blocks.splice(info.blocks.length - 1, 1)

                const lastBrick = sender.getChildByName("放置").children[sender.getChildByName("放置").children.length - 1]
                lastBrick.removeFromParent()
            }
        } else {
            info.x = x
            info.z = z
            
            if (this.isOperateFloor) {            
                if (info.blocks.length <= 0) {
                    info.isOpened = !info.isOpened
                    sender.getChildByName("六边形").getChildByName("内边").active = info.isOpened
                }
            } else {
                if (this.isRandomAdd) {
                    const count = parseInt(this.ui.brickCountInput.string)
                    if (count > Config.colorCount) {
                        console.error("输出的数超出颜色数量，输入数值需要小于 " + Config.colorCount)
                        return
                    } else {
                        var colorArr = []
                        for (var i = 0; i < Config.colorCount; i++) {
                            if (info.blocks.length > 0) {
                                if (info.blocks[info.blocks.length - 1] == i)
                                    continue
                            }
                            colorArr.push(i)
                        }
    
                        colorArr = Config.shuffle(colorArr)
                        colorArr = colorArr.splice(0, count)
                    }

                    for (var i = 0; i < colorArr.length; i++) {
                        info.blocks.push(colorArr[i])
                    }
                } else {
                    info.blocks.push(this.currentColor)
                }
                info.isOpened = true
                this.updateBrick(x, z, info)
            }
        }
    }

    // 点击颜色
    private colorClicked(event, customEventData) {
        this.currentColor = parseInt(customEventData)
        this.ui.currentColorSprite.spriteFrame = event.target.getComponent(Sprite).spriteFrame

        if (this.isOperatePool == true) {
            if (this.curBundle < 0) {
                this.nextBundle()
            }

            this.colors[this.curBundle].push(this.currentColor)
            this.contentAddBlock(this.currentColor)
        } else if (this.isSelectColor == true) {
            event.target.parent.getChildByName("背景").active = !event.target.parent.getChildByName("背景").active
        }
    }

    // 移除
    private removeBrick() {
        if (this.ui.currentBrick) {
            const arr = this.ui.currentBrick.string.split("_")
            const x = parseInt( arr[0] )
            const z = parseInt( arr[1] )
    
            this.grids[x][z] = new PointInfo()
            this.updateBrick(x, z, this.grids[x][z])
        }
    }

    // 导出
    private daoChuClicked() {
        const dir = {
            colors: this.colors,
            grids: this.grids,
            max: (this.ui.maxInput.string == null || this.ui.maxInput.string == "") ? 0 : parseInt(this.ui.maxInput.string),
            scale: this.ui.scaleInput.string
        }
        
        if (dir.max <= 0) {
            console.error("最高位为 0 ，请设置更高数值")
        }
        console.log (JSON.stringify(dir))
    }

    // 读取
    private duQuClicked() {
        this.grids = []
        const jsonGrids = this.targetJson.json["grids"]

        for (var ix = 0; ix < jsonGrids.length; ix++) {
            const rows = []
            for (var iz = 0; iz < jsonGrids[ix].length; iz++) {
                rows.push(new PointInfo())
            }

            this.grids.push(rows)
        }

        for (var ix = 0; ix < jsonGrids.length; ix++) {
            for (var iz = 0; iz < jsonGrids[ix].length; iz++) {
                const info = jsonGrids[ix][iz]
                this.grids[ix][iz] = info
                this.updateBrick(ix, iz, this.grids[ix][iz])
            }
        }

        const jsonColors = this.targetJson.json["colors"]
        this.colors = []
        for (var ix = 0; ix < jsonColors.length; ix++) {
            this.nextBundle()
            for (var iy = 0; iy < jsonColors[ix].length; iy++) {
                const getColor = jsonColors[ix][iy]
                
                this.colors[this.curBundle].push(getColor)
                this.contentAddBlock(getColor)
            }
        }

        this.ui.maxInput.string = this.targetJson.json["max"]
    }

    // 重置
    private chongZhiClicked() {
        this.curBundle = -1
        this.colors = []
        this.pointLoc = 10
        this.ui.scrollView.content.removeAllChildren()
        const scale = parseFloat(this.ui.scaleInput.string)
        console.log ("内容 = " + scale)
        this.operateCtrl.floorNode.scale = new Vec3(scale, scale, scale)
        this.initGround()
    }

    // 切换操作颜色池子
    private checkToggleEvent(toggle: Toggle) {
        // 是否选中
        const isCheck = toggle.isChecked
        if (isCheck) {
            this.ui.bottomNode.active = true
            this.isOperatePool = true

            this.ui.floorToggle.isChecked = false
            this.isOperateFloor = false
        } else {
            this.ui.bottomNode.active = false
            this.isOperatePool = false
        }
    }

    // 切换操作地板
    private checkFloorEvent(toggle: Toggle) {
        // 是否选中
        const isCheck = toggle.isChecked
        if (isCheck) {
            this.ui.bottomNode.active = false
            this.isOperateFloor = true

            this.ui.poolToggle.isChecked = false
            this.isOperatePool = false
        } else {
            this.isOperateFloor = false
        }
    }

    // 切换是否移出最高一个
    private checkRemoveLast(toggle: Toggle) {
        // 是否选中
        this.isOperateRemove = toggle.isChecked
    }

    // 切换是否添加随机颜色
    private checkAddRandom(toggle: Toggle) {
        this.isRandomAdd = toggle.isChecked

        console.log(this.ui.brickCountInput.string)
    }

    // 切换当前选中颜色
    private checkSelectColor(toggle: Toggle) {
        this.isSelectColor = toggle.isChecked
    }

    private cleanColorPool() {
        this.curBundle = -1
        this.colors = []
        this.pointLoc = 10
        this.ui.scrollView.content.removeAllChildren()
    }

    // 操作下一捆
    private nextBundle() {
        this.curBundle += 1
        this.colors[this.curBundle] = []

        const idNode = new Node()
        idNode.layer = Layers.Enum.UI_2D
        idNode.addComponent(Label).string = this.curBundle + ""
        idNode.getComponent(Label).color = new Color(0xFF000000)
        idNode.position = new Vec3(this.pointLoc, 0, 0)
        this.ui.scrollView.content.addChild(idNode)

        console.log ("添加 =====> ")
        this.pointLoc += 50
    }

    // 添加一层
    private addOneFloor() {
        
        for (var ix = 0; ix < this.grids.length; ix++) {
            for (var iz = 0; iz < this.grids[ix].length; iz++) {
                const info = this.grids[ix][iz]
                if (info.isOpened) {
                    var colorsArr = this.ui.getColorActives()

                    // 首先保证不和下面的一样
                    Config.removeFromArray(colorsArr, [info.blocks[info.blocks.length - 1]])
                    
                    const closees = this.getRimTower(ix, iz)
                    for (var i = 0; i < closees.length; i++) {
                        const close = closees[i]
                        if (close.blocks.length > 0) {
                            Config.removeFromArray(colorsArr, [close.blocks[close.blocks.length - 1]])
                        }
                    }
                    
                    if (colorsArr.length == 0) {
                        colorsArr = this.ui.getColorActives()
                    }


                    // this.isRandomAdd = toggle.isChecked

                    // console.log(this.ui.brickCountInput.string)

                    const count = this.isRandomAdd ? parseInt(this.ui.brickCountInput.string) : RandomUtil.randomInteger(3, 6)
                    const color = colorsArr[Math.floor(Math.random() * colorsArr.length)]

                    for (var i = 0; i < count; i++) {
                        info.blocks.push(color)
                    }
                
                    this.updateBrick(ix, iz, info)
                }
            }
        }
    }
}


